package no.gnet.edvd.cron;

import java.io.FileInputStream;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLConnection;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.util.Iterator;
import java.util.Map;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import no.gnet.edvd.DataStore;
import no.gnet.edvd.engines.Engine;
import no.gnet.edvd.feed.FeedReader;
import no.gnet.edvd.feed.types.RemoteMatch;
import no.gnet.edvd.types.MatchEvent;
import no.gnet.edvd.types.Player;
import no.gnet.edvd.util.Mailer;

import org.apache.commons.codec.binary.Base64;
import org.apache.log4j.Logger;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

public class ImportJob {

	Logger logger = Logger.getLogger(ImportJob.class);

	Player systemplayer = null;

	DataStore datastore;

	Engine engine;

	Mailer mailer;

	private static String apikeyencrypted = "glNtCGmKbY9eGftp6EDaKHGy4CRDZ364iO1tYJKEtHI=";

	private String baseURL = "http://football-api.com/api/";
	// =&from_date=31.08.2014&to_date=06.09.2014&match_date=31.08.2014"

	private String keypath = "/usr/edvd/edvd.jks";

	public void execute() throws Exception {
		System.out.println("Yeay");
		int matchcount = 0;
		for (int day = 1; day < 31; day++) {
			matchcount += importMatches(day);
		}
		logger.warn("***********");
		logger.warn("JOB DONE. NUMBER OF IMPORTED MATCHES IS " + matchcount);
		logger.warn("***********");

		if (matchcount > 0) {
			mailer.sendHtmlMail("EddeVedde", "gautesmaaland@gmail.com",
					"Matches have been imported",
					"<h2>Matches have been imported automatically</h2>. <p>How many? Well, it's "
							+ matchcount+"<p>. Greetings from the import-robot at an <i>EddeVedde</i> server");
		}

	}

	private int importMatches(int day) throws Exception {
		Map<RemoteMatch, MatchEvent> matches;
		matches = loadMatches(day);
		int matchcount=0;
		for (Iterator<RemoteMatch> iterator = matches.keySet().iterator(); iterator
				.hasNext();) {
			RemoteMatch remoteM = iterator.next();
			MatchEvent matchEvent = matches.get(remoteM);
			matchEvent.owner = this.getSystemUser();
			logger.debug("About to store " + remoteM + "/" + matchEvent);
			boolean importedOk=false;
			try {
				datastore.storeImportedMatchEvent(matchEvent, remoteM);
				importedOk=true;
			} catch (Exception e) {
				logger.warn("Match already imported: "
						+ remoteM.match_static_id);
			}
			if (importedOk) {
				logger.debug("Just stored " + remoteM + "/" + matchEvent);
				int evid = matchEvent.id;
				logger.debug("Activating " + evid);
				datastore.activateEvent(evid);
				logger.warn("Just stored and activated " + evid);
				matchcount++;
			}
		}
		return matchcount;
	}

	private Map<RemoteMatch, MatchEvent> loadMatches(int indays)
			throws Exception {
		String url = createURL(indays);
		URLConnection urlconn = new URL(url).openConnection();
		Map<RemoteMatch, MatchEvent> matches = new FeedReader()
				.readMatchesFromStream(urlconn.getInputStream());
		return matches;
	}

	private String createURL(int indays) throws Exception {
		String u = baseURL + "?APIKey=" + getAPIKey() + "&Action=fixtures"
				+ "&match_date=" + dateInDays(indays);
		logger.debug("Url is " + u);
		return u;
	}

	private String dateInDays(int nOfDays) {
		DateTime today = new DateTime();
		DateTime indays = today.plusDays(nOfDays);
		DateTimeFormatter dtf = DateTimeFormat.forPattern("dd.MM.yyyy");
		return dtf.print(indays);
	}

	private String getAPIKey() throws Exception {
		KeyStore keyStore = KeyStore.getInstance("JCEKS");
		FileInputStream stream = new FileInputStream(keypath);
		keyStore.load(stream, "mercedes".toCharArray());
		Key key = keyStore.getKey("edvdkey", "mercedes".toCharArray());
		return decryptWithAESKey(apikeyencrypted, key.getEncoded());
	}

	public static void main(String[] args) {
		try {
			// new ImportJob().execute();

			// String data=args[2];
			//
			// //Encrypt Data
			// String encryptedData = encryptWithAESKey(data, key.getEncoded());
			// System.out.println("Encrypted Data : " + encryptedData);
			// //Decrypt Data
			// System.out.println("Decrypted Data : "
			// +decryptWithAESKey(encryptedData, key.getEncoded()));

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	public static String encryptWithAESKey(String data, byte[] key)
			throws NoSuchAlgorithmException, NoSuchPaddingException,
			InvalidKeyException, IllegalBlockSizeException,
			BadPaddingException, UnsupportedEncodingException {
		SecretKey secKey = new SecretKeySpec(key, "AES");

		Cipher cipher = Cipher.getInstance("AES");

		cipher.init(Cipher.ENCRYPT_MODE, secKey);
		byte[] newData = cipher.doFinal(data.getBytes());

		return Base64.encodeBase64String(newData);
	}

	public static String decryptWithAESKey(String inputData, byte[] key)
			throws NoSuchAlgorithmException, NoSuchPaddingException,
			InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
		Cipher cipher = Cipher.getInstance("AES");
		SecretKey secKey = new SecretKeySpec(key, "AES");

		cipher.init(Cipher.DECRYPT_MODE, secKey);
		byte[] newData = cipher.doFinal(Base64.decodeBase64(inputData
				.getBytes()));
		return new String(newData);

	}

	private Player getSystemUser() {
		if (systemplayer == null) {
			Player player = Player.getSystemUser();
			if (!datastore.playerExists(player)) {
				systemplayer = datastore.storePlayer(player);
			} else {
				systemplayer = datastore.getPlayer(player);
			}
		}
		return systemplayer;
	}

	public Mailer getMailer() {
		return mailer;
	}

	public void setMailer(Mailer mailer) {
		this.mailer = mailer;
	}

	public Engine getEngine() {
		return engine;
	}

	public void setEngine(Engine engine) {
		this.engine = engine;
	}

	public DataStore getDatastore() {
		return datastore;
	}

	public void setDatastore(DataStore datastore) {
		this.datastore = datastore;
	}

}
